#pragma once

#ifdef PUNCH_MSGPACK
#include <msgpack.hpp>
#endif

#include "../internal/sdeque.h"

namespace mdtx::punch::smatch
{
    /**
     * @brief Basic quote type can be used in smatch engine
     *
     * @tparam TI id type
     * @tparam TQ quantity type
     */
    template <typename TI, typename TQ>
    struct Quote
    {
        using id_type = TI;
        using quant_type = TQ;

        TQ price, quant;
        TI cli_id, seq_id;

#ifdef PUNCH_MSGPACK
        MSGPACK_DEFINE_ARRAY(price, quant, cli_id, seq_id);

        Quote()
        {
        }
#endif

        Quote(TQ price, TQ quant)
            : price{price}, quant{quant},
              cli_id{}, seq_id{}
        {
        }

        /**
         * @brief Construct a new Quote object
         *
         * @details instrument id is not used in smatch::Quote because each
         * smath::Engine only serves one instrument, ins_id is defined in
         * Engine instance instead of orders.
         *
         * @param price price
         * @param quant quantity
         * @param cli_id client id
         */
        Quote(TQ price, TQ quant, TI cli_id)
            : price{price}, quant{quant},
              cli_id{cli_id}, seq_id{}
        {
        }

        void set_cli(TI cli_id)
        {
            this->cli_id = cli_id;
        }

        void set_seq(TI seq_id)
        {
            this->seq_id = seq_id;
        }

        struct BidComparator
        {
            bool operator()(const Quote &lhs, const Quote &rhs) const
            {
                return (lhs.price > rhs.price) || (lhs.price == rhs.price && lhs.seq_id < rhs.seq_id);
            }

            static constexpr bool better_price(TQ lhs, TQ rhs)
            {
                return lhs > rhs;
            }
        };

        struct AskComparator
        {
            bool operator()(const Quote &lhs, const Quote &rhs) const
            {
                return (lhs.price < rhs.price) || (lhs.price == rhs.price && lhs.seq_id < rhs.seq_id);
            }

            static constexpr bool better_price(TQ lhs, TQ rhs)
            {
                return lhs < rhs;
            }
        };
    };
}
